package com.jzr.medical.auth;

import com.jzr.medical.db1.service.MyUserDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.header.Header;
import org.springframework.security.web.header.writers.StaticHeadersWriter;

import java.util.Arrays;

/**
 *
 */
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {

    @Configuration
    public static class MySecurityConfig extends WebSecurityConfigurerAdapter {

        @Autowired
        @Qualifier("databaseUserDetailService")
        private MyUserDetailService userDetailsService;

        @Autowired
        @Qualifier("authenticationSuccessHandler")
        private AuthenticationSuccessHandler successHandler;

        @Autowired
        @Qualifier("authenticationFailHandler")
        private AuthenticationFailHandler failHandler;

        @Autowired
        @Qualifier("authenticationEntryPointImpl")
        private AuthenticationEntryPoint entryPoint;

        //@Bean不能放到ioc容器里，否则会引起ignoring绕不过这个filter
        public JwtAuthenticationFilter getJwtAuthenticationFilter(){
            return new JwtAuthenticationFilter();
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                //.antMatchers("/**").permitAll()
                .anyRequest().authenticated()//任何请求登录后访问
                .and()
                //基于token，所以不需要session
                //.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
                //.sessionManagement() //会话管理
                //.maximumSessions(1); //限制登录人数
                .and().csrf().disable();

            //登录操作
            http.formLogin()
                //.loginPage("/login.html")//登录路径
                .loginProcessingUrl("/api/user/login")//登录表单提交请求
                .usernameParameter("username")//设置登录账号参数，默认username
                .passwordParameter("password")//设置登录密码参数，默认password
                //.defaultSuccessUrl("/home.html")//登录成功跳转，不能和successHandler一起使用
                //.failureUrl("/login.html")// 登录失败跳转，不能和failureHandler一起使用
                .permitAll()
                //登录成功处理
                .successHandler(successHandler)
                //登录失败处理
                .failureHandler(failHandler);

            //退出操作
            http.logout()
                .logoutUrl("/api/user/logout"); //退出提交参数
                //.logoutSuccessUrl("/login.html");//退出后跳转，不能和logoutSuccessHandler一起使用
                //.logoutSuccessHandler();//退出处理

            //禁用缓存
            http.headers().cacheControl();

            http.headers().addHeaderWriter(new StaticHeadersWriter(Arrays.asList(
                    new Header("Access-control-Allow-Origin","*"),
                    new Header("Access-Control-Expose-Headers","Authorization"))));

            http.addFilterBefore(getJwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                    // 添加权限不足 filter
                    .exceptionHandling().accessDeniedHandler(new MyAccessDeniedHandler())
                    //其他异常处理类
                    .authenticationEntryPoint(new MyAuthenticationException());

            /*
            http.addFilterBefore(getJwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
                    .and().csrf().disable()
                    .authorizeRequests()
                    .anyRequest().authenticated()
                    .and().formLogin()
                        //.loginPage("/admin/login.html")
                        .loginProcessingUrl("/api/user/login").permitAll()
                    .successHandler(successHandler)
                    .failureHandler(failHandler)
                    .and().cors() //支持跨域
                    .and()   //添加header设置，支持跨域和ajax请求
                    .headers().addHeaderWriter(new StaticHeadersWriter(Arrays.asList(
                        new Header("Access-control-Allow-Origin","*"),
                        new Header("Access-Control-Expose-Headers","Authorization"))))
                    .and().exceptionHandling().authenticationEntryPoint(entryPoint);
            */
        }

        @Bean
        public MyPasswordEncoder myPasswordEncoder(){
            return new MyPasswordEncoder();
        }

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService).passwordEncoder(myPasswordEncoder());
        }

        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring()
                    // swagger
                    .antMatchers("/swagger-ui.html","/swagger-resources/**",
                            "/images/**","/webjars/**","/v2/api-docs",
                            "/configuration/ui","/configuration/security")
                    // others
                    .antMatchers("/test/**","/open/**","/favicon.ico"
                            ,"/api/user/checkLogin", "/file/**");
        }
    }
}
